package com.example.apartment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.apartment.common.RespException;
import com.example.apartment.common.RespExceptionEnum;
import com.example.apartment.domain.*;
import com.example.apartment.mapper.BedMapper;
import com.example.apartment.mapper.BuildingMapper;
import com.example.apartment.mapper.RoomMapper;
import com.example.apartment.mapper.StudentMapper;
import com.example.apartment.service.RoomService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 宿舍业务层实现类
 *
 * @author wuzexin
 * @date 2021/11/2 15:34
 */
@Service
public class RoomServiceImpl implements RoomService {

    @Resource
    private RoomMapper roomMapper;
    @Resource
    private BedMapper bedMapper;
    @Resource
    private BuildingMapper buildingMapper;
    @Resource
    private StudentMapper studentMapper;

    /*
        判断管理员是否拥有权限
        role: 1-系统管理员 2-宿舍楼管理员 3-未审核不可登录状态
        只有系统管理员和对应楼栋的宿舍楼管理员才有权限进行操作
     */

    /**
     * 创建宿舍
     *
     * @param admin        管理员用户信息
     * @param roomNum      宿舍号
     * @param personCount  可住人数
     * @param price        住宿费用
     * @param buildingName 宿舍楼名字
     * @return 宿舍信息
     */
    @Override
    public Room create(Admin admin, Integer roomNum, Integer personCount, Integer price, String buildingName) {

        QueryWrapper builQueryWrapper = new QueryWrapper();
        builQueryWrapper.eq("building_name", buildingName);
        Building building = buildingMapper.selectOne(builQueryWrapper);
        // 判断宿舍楼是否存在
        if (building == null) {
            // 不存在，则抛出宿舍楼不存在异常
            throw new RespException(RespExceptionEnum.BUILDING_NOT_EXISTS);
        }

        Integer buildingId = building.getId();

        // 判断用户是否为系统管理员 或者为该楼栋的宿舍管理员
        if ((admin.getRole() != 1) && !(admin.getRole() == 2 && admin.getBuildingId().equals(buildingId))) {
            // 不是则抛出权限不够异常
            throw new RespException(RespExceptionEnum.NEED_PERMISSIONS);
        }

        // 判断宿舍号是否已经存在
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("building_id", buildingId);
        queryWrapper.eq("room_num", roomNum);
        Room room1 = roomMapper.selectOne(queryWrapper);
        if (room1 != null) {
            // 如果宿舍号已经存在，则抛出异常
            throw new RespException(RespExceptionEnum.ROOM_NUM_EXISTS);
        }

        // 创建一个room对象，将信息封装在room对象中
        Room room = new Room();
        room.setRoomNum(roomNum);
        room.setPrice(price);
        room.setPersonCount(personCount);
        room.setBuildingId(buildingId);

        // 写入数据库
        int insert = roomMapper.insert(room);

        // 如果数据未写入，则抛出新增失败异常
        if (insert == 0) {
            throw new RespException(RespExceptionEnum.INSERT_FAILED);
        }

        return room;
    }

    /**
     * 更改宿舍信息
     *
     * @param admin       管理员用户信息
     * @param id          宿舍id
     * @param roomNum     新宿舍号
     * @param personCount 新宿舍可住人数
     * @param price       新住宿费用
     * @param buildingId  宿舍楼id
     * @return 宿舍信息
     */
    @Override
    public Room update(Admin admin, Integer id, Integer roomNum, Integer personCount, Integer price, Integer buildingId) {

        // 判断用户是否为系统管理员 或者为该楼栋的宿舍管理员
        if (admin.getRole() != 1 && !(admin.getRole() == 2 && admin.getBuildingId().equals(buildingId))) {
            // 不是则抛出权限不够异常
            throw new RespException(RespExceptionEnum.NEED_PERMISSIONS);
        }

        // 通过主键id，查询原房间信息
        Room room = roomMapper.selectById(id);

        // 如果room为空，则抛出房间不存在异常
        if (room == null) {
            throw new RespException(RespExceptionEnum.ROOM_NOT_EXISTS);
        }

        // 判断 roomNum 是否更改
        if (!room.getRoomNum().equals(roomNum)) {

            // 如果更改，查询新宿舍号时候已存在
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("building_id", buildingId);
            queryWrapper.eq("room_num", roomNum);
            Room room1 = roomMapper.selectOne(queryWrapper);

            // 如果已存在，则抛出异常
            if (room1 != null) {
                throw new RespException(RespExceptionEnum.ROOM_NUM_EXISTS);
            }

            room.setRoomNum(roomNum);
        }

        room.setPrice(price);
        room.setPersonCount(personCount);

        // 写入数据库
        int update = roomMapper.updateById(room);

        // 如果数据未写入，则抛出新增失败异常
        if (update == 0) {
            throw new RespException(RespExceptionEnum.UPDATE_FAILED);
        }

        return room;
    }

    /**
     * 删除宿舍
     *
     * @param admin 管理员用户信息
     * @param id    宿舍id
     */
    @Override
    public void delete(Admin admin, Integer id) {

        // 获取该roomId 所对应的buildingId
        Room room = roomMapper.selectById(id);
        Integer buildingId = room.getBuildingId();

        // 判断用户是否为系统管理员 或者为该楼栋的宿舍管理员
        if (admin.getRole() != 1 && !(admin.getRole() == 2 && admin.getBuildingId().equals(buildingId))) {
            // 不是则抛出权限不够异常
            throw new RespException(RespExceptionEnum.NEED_PERMISSIONS);
        }

        // 判断该房间是否还存在对应床位信息
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("room_id", id);
        List<Bed> list = bedMapper.selectList(queryWrapper);
        if (!list.isEmpty()) {
            // 如果宿舍不为空则抛出异常
            throw new RespException(RespExceptionEnum.ROOM_NOT_EMPTY);
        }

        // 操作数据库
        int delete = roomMapper.deleteById(id);

        // 如果数据库操作不成功，则抛出删除失败异常
        if (delete != 1) {
            throw new RespException(RespExceptionEnum.DELETE_FAILED);
        }
    }

    /**
     * 查询所有宿舍信息
     *
     * @param admin 管理员用户信息
     * @return 所有宿舍信息
     */
    @Override
    public List<Room> select(Admin admin) {

        int role = admin.getRole();
        List<Room> list = null;

        if (role == 1) {
            // 系统管理员可以查询所有宿舍信息
            list = roomMapper.selectList(null);

        } else if (role == 2) {
            // 宿舍管理员只能查询所负责楼栋的宿舍信息
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("building_id", admin.getBuildingId());
            list = roomMapper.selectList(queryWrapper);

        } else {
            throw new RespException(RespExceptionEnum.NEED_PERMISSIONS);
        }

        return list;
    }

    /**
     * 根据buildingName查询宿舍楼所有宿舍房间
     *
     * @param admin        管理员信息
     * @param buildingName 宿舍楼名字
     * @return 宿舍房间列表
     */
    @Override
    public List<Room> selectByBuildingName(Admin admin, String buildingName) {

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("building_name", buildingName);
        Building building = buildingMapper.selectOne(queryWrapper);

        // 如果building不存在，则抛出宿舍楼不存在异常
        if (building == null) {
            throw new RespException(RespExceptionEnum.BUILDING_NOT_EXISTS);
        }

        List<Room> list = null;

        if (admin.getRole() == 1 || (admin.getRole() == 2 && admin.getBuildingId() == building.getId())) {

            // 根据building_id查到所有房间
            QueryWrapper roomQueryWrapper = new QueryWrapper();
            roomQueryWrapper.eq("building_id", building.getId());
            roomQueryWrapper.orderByAsc("room_num");
            list = roomMapper.selectList(roomQueryWrapper);
        } else {
            // 抛出权限不够异常
            throw new RespException(RespExceptionEnum.NEED_PERMISSIONS);
        }

        // 查询building_id对应的buildingName
        for (Room room : list) {
            Building buil = buildingMapper.selectById(room.getBuildingId());
            room.setBuildingName(buil.getBuildingName());
        }

        return list;
    }

    /**
     * 根据id查询宿舍信息
     *
     * @param admin 管理员信息
     * @param id    房间主键id
     * @return 房间信息
     */
    @Override
    public Room selectById(Admin admin, Integer id) {

        // 获取该roomId 所对应的buildingId
        Room room = roomMapper.selectById(id);

        // 如果room为空，则抛出宿舍不存在异常
        if (room == null) {
            throw new RespException(RespExceptionEnum.ROOM_NOT_EXISTS);
        }

        Integer buildingId = room.getBuildingId();

        // 判断用户是否为系统管理员 或者为该楼栋的宿舍管理员
        if (admin.getRole() != 1 && !(admin.getRole() == 2 && admin.getBuildingId().equals(buildingId))) {
            // 不是则抛出权限不够异常
            throw new RespException(RespExceptionEnum.NEED_PERMISSIONS);
        }

        // 查询该宿舍对应的buildingName
        Building building = buildingMapper.selectById(room.getBuildingId());
        room.setBuildingName(building.getBuildingName());

        // 返回宿舍信息
        return room;
    }

    /**
     * 查询某栋宿舍楼，所有包含四个空床位的空宿舍数量
     *
     * @param admin
     * @param buildingName
     * @return
     */
    @Override
    public int selectEmptyRoomCount(Admin admin, String buildingName) {

        // 如果不是系统管理员，则抛出权限不够异常
        if (admin.getRole() != 1) {
            throw new RespException(RespExceptionEnum.NEED_PERMISSIONS);
        }

        // 通过buildingName, 获得buildingId
        QueryWrapper buildingQueryWrapper = new QueryWrapper();
        buildingQueryWrapper.eq("building_name", buildingName);
        Building building = buildingMapper.selectOne(buildingQueryWrapper);

        // 查询该宿舍楼的所有房间列表
        QueryWrapper roomListQueryWrapper = new QueryWrapper();
        roomListQueryWrapper.eq("building_id", building.getId());
        List<Room> roomList = roomMapper.selectList(roomListQueryWrapper);

        int count = 0;

        // 遍历宿舍房间列表
        for (Room room : roomList) {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("building_id", building.getId());
            queryWrapper.eq("room_id", room.getId());

            // 获得床位列表
            List<Bed> list = bedMapper.selectList(queryWrapper);

            // 如果有该房间有4个床位，则判断，4个床位是不是都没人居住
            if (list.size() != 4) {
                continue;
            }

            // 用来判断床位有人居住就跳出循环
            boolean flag = true;

            for (Bed bed : list) {
                QueryWrapper stuQueryWrapper = new QueryWrapper();
                stuQueryWrapper.eq("bed_id", bed.getId());
                Student student = studentMapper.selectOne(stuQueryWrapper);
                if (student != null) {
                    flag = true;
                    break;
                }
            }

            if (flag) {
                // 数量+1
                count ++;
            }
        }

        return count;
    }
}
